package org.example;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class APIMonitoringAspect {

    static Map<String, Integer> apiCallCounts = new HashMap<>();
    static Map<String, Long> apiTotalResponseTime = new HashMap<>();
    static Map<String, Long> apiMinResponseTime = new HashMap<>();
    static Map<String, Long> apiMaxResponseTime = new HashMap<>();
    static Map<String, Integer> apiExceptionCounts = new HashMap<>();

    @Before("execution(* your.package.name..*.*(..))")
    public void beforeMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().toShortString();
        apiCallCounts.put(methodName, apiCallCounts.getOrDefault(methodName, 0) + 1);
        apiTotalResponseTime.put(methodName, apiTotalResponseTime.getOrDefault(methodName, 0L));
        StopWatch stopWatch = new StopWatch();
        stopWatch.start(methodName);
        joinPoint.getArgs();
    }

    @AfterReturning(value = "execution(* your.package.name..*.*(..))", returning = "result")
    public void afterMethod(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().toShortString();
        StopWatch stopWatch = new StopWatch();
        stopWatch.stop();
        long elapsedTime = stopWatch.getTotalTimeMillis();
        apiTotalResponseTime.put(methodName, apiTotalResponseTime.get(methodName) + elapsedTime);
        apiMinResponseTime.put(methodName, Math.min(apiMinResponseTime.getOrDefault(methodName, Long.MAX_VALUE), elapsedTime));
        apiMaxResponseTime.put(methodName, Math.max(apiMaxResponseTime.getOrDefault(methodName, 0L), elapsedTime));
    }

    @AfterThrowing(value = "execution(* your.package.name..*.*(..))", throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint, Throwable exception) {
        String methodName = joinPoint.getSignature().toShortString();
        apiExceptionCounts.put(methodName, apiExceptionCounts.getOrDefault(methodName, 0) + 1);
    }
}